package com.aifast.system.sys.service;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.aifast.common.base.BaseEntity;
import com.aifast.common.cache.util.RedisUtil;
import com.aifast.common.global.Const;
import com.aifast.common.layui.LayuiDataTable;
import com.aifast.common.layui.LayuiPageFactory;
import com.aifast.common.util.AiUtil;
import com.aifast.common.util.XmTree;
import com.aifast.system.sys.dao.SysDictDataDao;
import com.aifast.system.sys.entity.SysDict;
import com.aifast.system.sys.entity.SysDictData;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jfinal.kit.Kv;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 字典数据 服务实现类
 * </p>
 *
 * @author fujian
 * @since 2021-12-30
 */
@Service
@RequiredArgsConstructor
public class SysDictDataService extends ServiceImpl<SysDictDataDao, SysDictData> {

    private final SysDictService sysDictService;

    /**
     * 列表查询方法
     *
     * @param dictId       字典id
     * @param dictDataName 字典名称
     * @param dictDataCode 字典code
     * @param page         分页
     * @return
     */
//    @GraceRecorder(success = "用户查看字典类别为{#dictId}的字典项列表页 ,页码{#page.current} ,页数{#page.size} , 搜索条件为 dictDataName: {#dictDataName} ,dictDataCode : {#dictDataCode}"
//    ,category = "log")
//    @AiLog(success = "用户查看字典类别为{#dictId}的字典项列表页 ,页码{#page.current} ,页数{#page.size} , 搜索条件为 dictDataName: {#dictDataName} ,dictDataCode : {#dictDataCode}")
    public LayuiDataTable getDatas(Integer dictId, String dictDataName, String dictDataCode, Page page) {
        LambdaQueryWrapper<SysDictData> wrapper = new LambdaQueryWrapper<SysDictData>()
                .eq(SysDictData::getPid, dictId)
                .like(StrUtil.isNotBlank(dictDataName), SysDictData::getName, dictDataName)
                .like(StrUtil.isNotBlank(dictDataCode), SysDictData::getType, dictDataCode)
                .orderByDesc(SysDictData::getSort);
        return LayuiPageFactory.init(page(page, wrapper));
    }

    /**
     * 新增或修改
     *
     * @param data
     * @return
     */
//    @LogRecordAnnotation(success = "{{#data.id == null ? '新增' : '修改'}}字典项Dict {{#data.name}} ,操作结果{{#_ret ? '成功' : '失败'}}",prefix = Table.SYS_DICT_DATA
//            ,bizNo = "{{#data.id}}",detail = "{{#data.toString()}}")
    public Boolean insertOrUpdate(SysDictData data) {
        if (ObjectUtil.isNull(data.getId())) {
            refreshDictMap(data.getType(), null);
        } else {
            refreshDictMap(data.getType(), data.getValue());
        }
        return saveOrUpdate(data);
    }

    /**
     * 批量新增操作
     *
     * @param data
     * @return
     */
    @Transactional
    public boolean batchAdd(SysDictData data) {
        String[] names = data.getName().split(" ");
        String[] values = data.getValue().split(" ");
        if (ObjectUtil.notEqual(names.length, values.length)) {
            AiUtil.alert("字典项名称和值的数量不一致");
        }
        for (int i = 0; i < names.length; i++) {
            SysDictData build = SysDictData.builder().pid(data.getPid()).type(data.getType()).build();
            build.setName(names[i]);
            build.setValue(values[i]);
            Boolean aBoolean = this.insertOrUpdate(build);
            if (!aBoolean) {
                return false;
            }
        }
        return true;
    }

    /**
     * 删除 和 批量删除
     *
     * @param id  数据id
     * @param ids 数据id集合
     * @return
     */
    public boolean del(Integer id, String ids) {
        List<Integer> integers = new ArrayList<>();
        if (StrUtil.isNotBlank(ids)) {
            integers = Convert.toList(Integer.class, ids.split(","));
        }
        if (!Objects.equals(null, id)) {
            integers.add(id);
        }
        try {
            integers.forEach(i -> {
                update(new UpdateWrapper<SysDictData>().set("deleted", 1).eq("id", i));
            });
            return true;
        } catch (Exception e) {
            return false;
        }

    }

    public Object get(String... dict) {
        QueryWrapper<SysDictData> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("state", 0).orderByDesc("sort");
        List<SysDictData> list;
        Map<String, List<SysDictData>> env = new HashMap<>();
        if (ObjectUtil.isNull(dict) || dict.length == 0) {
            list = list(queryWrapper);
            List<String> collect = list.stream().map(SysDictData::getType).distinct().collect(Collectors.toList());
            for (String s : collect) {
                List<SysDictData> collect1 = list.stream().filter(i -> StrUtil.equals(s, i.getType())).collect(Collectors.toList());
                env.put(s, collect1);
            }
            return env;
        }

        if (dict.length > 1) {
            queryWrapper.in("type", dict);
            list = list(queryWrapper);
            List<String> collect = list.stream().map(SysDictData::getType).distinct().collect(Collectors.toList());
            for (String s : collect) {
                List<SysDictData> collect1 = list.stream().filter(i -> StrUtil.equals(s, i.getType())).collect(Collectors.toList());
                env.put(s, collect1);
            }
            return env;
        }

        list = list(new QueryWrapper<SysDictData>().eq("type", dict[0]).orderByDesc("sort"));
        env.put(dict[0], list);
        return env;
    }

    /**
     * 用于获取字典数据中模式为多层级的数据
     *
     * @param type
     * @return
     */
    public Object getTree(String... type) {
        QueryWrapper<SysDictData> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("state", 0).orderByDesc("sort");
        List<SysDict> dicts = sysDictService.getByMode(1);
        List<Integer> collect = dicts.stream().map(BaseEntity::getId).collect(Collectors.toList());
        if (collect.size() == 0) {
            collect.add(-1);
        }
        queryWrapper.in("pid", collect);
        List<SysDictData> list;
        Map<String, List<XmTree>> env = new HashMap<>();
        if (ObjectUtil.isNull(type) || type.length == 0) {
            return null;
        }
        if (type.length > 0) {
            queryWrapper.in("type", type);
            list = list(queryWrapper);
            List<String> types = list.stream().map(SysDictData::getType).distinct().collect(Collectors.toList());
            for (String s : types) {
                List<SysDictData> collect1 = list.stream().filter(i -> StrUtil.equals(s, i.getType())).collect(Collectors.toList());
                List<XmTree> init = XmTree.init(collect1.stream().map(i -> {
                    return XmTree.builder().pid(i.getDataPid()).name(i.getName()).value(i.getId()).tmpValue(i.getValue()).children(new ArrayList<XmTree>()).build();
                }).collect(Collectors.toList()));
                env.put(s, init);
            }
            return env;
        }

        return null;
    }

    /**
     * 获取对应字典转译后的值
     * <br>先从缓存字典里查找 查不到再走数据库 并更新字典缓存
     *
     * @param type       字典类型
     * @param fieldValue 字段的值
     * @return 对应的字典值
     */
    public String getDictDataValue(String type, Object fieldValue) {
        if (StrUtil.isBlank(type) || ObjectUtil.isNull(fieldValue)) {
            return "";
        }
//        Console.log("翻译字典" + type +",值" + fieldValue);
        String key = getDictMapKey(type);

        String hget = RedisUtil.hget(key, Convert.toStr(fieldValue));
        if (RedisUtil.exists(key) && StrUtil.isNotBlank(hget)) {
            return hget;
        }
        SysDictData one = getOne(new QueryWrapper<SysDictData>().eq("type", type).eq("value", fieldValue).last("limit 1"));

        initDictMap();
        return ObjectUtil.isNull(one) ? "" : one.getName();
    }

    /**
     * 实例化字典参数map
     */
    private void initDictMap() {
        List<SysDictData> list = list();
        List<String> collect = list.stream().map(SysDictData::getType).distinct().collect(Collectors.toList());
        collect.forEach(type -> {
            Map<String, Object> tmp = new HashMap<>();
            list.stream().forEach(l -> {
                if (StrUtil.equals(type, l.getType())) {
                    tmp.put(l.getValue(), l.getName());
                }
            });
            setDictMapCache(type, tmp);
        });
    }

    /**
     * 刷新字典map方法
     * 提供三种刷新方式
     * <ul>
     * <li>1、全局刷新 type和field参数传空即可</>
     * <li>2、局部刷新 传type参数field参数传空即可 例如 传type=》sex 会刷新sex下所有字典数据</>
     * <li>3、单个刷新 传type和field参数即可 例如 传type=》sex field=》1 会刷新 女 这一条字典数据     </>
     * <ul/>
     *
     * @param type
     * @param fieldValue
     */
    public void refreshDictMap(String type, String fieldValue) {
        if (StrUtil.isBlank(type) && StrUtil.isBlank(fieldValue)) {
            initDictMap();
        }

        if (StrUtil.isNotBlank(type) && StrUtil.isBlank(fieldValue)) {
            List<SysDictData> list = list(new QueryWrapper<SysDictData>().eq("type", type));
            if (list.size() > 0) {
                Map<String, Object> tmp = new HashMap<>();
                list.forEach(i -> {
                    tmp.put(i.getValue(), i.getName());
                });
                setDictMapCache(type, tmp);
            }

        }

        if (StrUtil.isNotBlank(type) && StrUtil.isNotBlank(fieldValue)) {
            SysDictData one = getOne(new QueryWrapper<SysDictData>().eq("type", type).eq("value", fieldValue).last("limit 1"));
            if (ObjectUtil.isNull(one)) {
                return;
            }
            String key = getDictMapKey(type);

            RedisUtil.hdel(key, fieldValue);
            RedisUtil.hset(key, fieldValue, one.getName());
        }

    }

    /**
     * 设置字典map缓存
     *
     * @param type 字典类型
     * @param map  字典map
     */
    private static void setDictMapCache(String type, Map<String, Object> map) {
        String key = getDictMapKey(type);
        RedisUtil.hset(key, map);
    }

    /**
     * 获取字典map的键值key
     *
     * @param type 字典类型
     * @return
     */
    private static String getDictMapKey(String type) {
        return StrUtil.join(":", Const.PROJECT_NAME_UC,"dict", "map", type);
    }


    public List<Kv> getMaps() {
        List<String> orderBy = new ArrayList<>();
        orderBy.add("sort");
        orderBy.add("id");
        List<Map<String, Object>> list = listMaps(new QueryWrapper<SysDictData>().orderByDesc(orderBy));
        List<Kv> maps = Convert.toList(Kv.class, list);
        return maps;

    }



}
